﻿// ISO C9x  compliant inttypes.h for Microsoft Visual Studio
// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 
// 
//  Copyright (c) 2006 Alexander Chemeris
// 
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// 
//   1. Redistributions of source code must retain the above copyright notice,
//      this list of conditions and the following disclaimer.
// 
//   2. Redistributions in binary form must reproduce the above copyright
//      notice, this list of conditions and the following disclaimer in the
//      documentation and/or other materials provided with the distribution.
// 
//   3. The name of the author may be used to endorse or promote products
//      derived from this software without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// 
///////////////////////////////////////////////////////////////////////////////

/********************************************************************
	created:	2011-8-10   16:11
	author:		Lifan Su
	
	purpose:	implement for <inttypes.h> for MSVC
                based on http://msinttypes.googlecode.com/svn/trunk/inttypes.h
*********************************************************************/

#ifndef INTTYPES_MSVC_H
#define INTTYPES_MSVC_H

#if !defined _INTTYPES_H && !defined _CINTTYPS_HPP
#error "Don't include this heeader, include _cinttypes.hpp or _inttypes.h"
#endif

#if !defined _MSC_VER
#error "Unsupported platform, did you just included this header?"
#endif

#ifdef __cplusplus
#include "../_cstdint.hpp"
#else // __cplusplus
#include "../_stdint.h"
#endif // __cplusplus

#include <crtdefs.h>
#include <sal.h>



// 7.8.1 Macros for format specifiers
#define PRId8           "hhd"
#define PRIi8           "hhi"
#define PRIdLEAST8      PRId8
#define PRIiLEAST8      PRIi8
#define PRIdFAST8       PRId8
#define PRIiFAST8       PRIi8

#define PRId16          "hd"
#define PRIi16          "hi"
#define PRIdLEAST16     PRId16
#define PRIiLEAST16     PRIi16
#define PRIdFAST16      PRId16
#define PRIiFAST16      PRIi16

#define PRId32          "I32d"
#define PRIi32          "I32i"
#define PRIdLEAST32     PRId32
#define PRIiLEAST32     PRIi32
#define PRIdFAST32      PRId32
#define PRIiFAST32      PRIi32

#define PRId64          "I64d"
#define PRIi64          "I64i"
#define PRIdLEAST64     PRId64
#define PRIiLEAST64     PRIi64
#define PRIdFAST64      PRId64
#define PRIiFAST64      PRIi64

#define PRIdMAX         PRId64
#define PRIiMAX         PRIi64

#if defined _M_X64 || _M_AMD64
#define PRIdPTR         PRId64
#define PRIiPTR         PRIi64
#elif defined _M_IX86
#define PRIdPTR         PRId32
#define PRIiPTR         PRIi32
#else
#error "Unsupported platform!"
#endif

// The fprintf macros for unsigned integers are:
#define PRIo8           "hho"
#define PRIu8           "hhu"
#define PRIx8           "hhx"
#define PRIX8           "hhX"
#define PRIoLEAST8      PRIo8
#define PRIuLEAST8      PRIu8
#define PRIxLEAST8      PRIx8
#define PRIXLEAST8      PRIX8
#define PRIoFAST8       PRIo8
#define PRIuFAST8       PRIu8
#define PRIxFAST8       PRIx8
#define PRIXFAST8       PRIX8

#define PRIo16          "ho"
#define PRIu16          "hu"
#define PRIx16          "hx"
#define PRIX16          "hX"
#define PRIoLEAST16     PRIo16
#define PRIuLEAST16     PRIu16
#define PRIxLEAST16     PRIx16
#define PRIXLEAST16     PRIX16
#define PRIoFAST16      PRIo16
#define PRIuFAST16      PRIu16
#define PRIxFAST16      PRIx16
#define PRIXFAST16      PRIX16

#define PRIo32          "I32o"
#define PRIu32          "I32u"
#define PRIx32          "I32x"
#define PRIX32          "I32X"
#define PRIoLEAST32     PRIo32
#define PRIuLEAST32     PRIu32
#define PRIxLEAST32     PRIx32
#define PRIXLEAST32     PRIX32
#define PRIoFAST32      PRIo32
#define PRIuFAST32      PRIu32
#define PRIxFAST32      PRIx32
#define PRIXFAST32      PRIX32

#define PRIo64          "I64o"
#define PRIu64          "I64u"
#define PRIx64          "I64x"
#define PRIX64          "I64X"
#define PRIoLEAST64     PRIo64
#define PRIuLEAST64     PRIu64
#define PRIxLEAST64     PRIx64
#define PRIXLEAST64     PRIX64
#define PRIoFAST64      PRIo64
#define PRIuFAST64      PRIu64
#define PRIxFAST64      PRIx64
#define PRIXFAST64      PRIX64

#define PRIoMAX         PRIo64
#define PRIuMAX         PRIu64
#define PRIxMAX         PRIx64
#define PRIXMAX         PRIX64


#if defined _M_X64 || _M_AMD64
    #define PRIoPTR         PRIo64
    #define PRIuPTR         PRIu64
    #define PRIxPTR         PRIx64
    #define PRIXPTR         PRIX64
#elif defined _M_IX86
    #define PRIoPTR         PRIo32
    #define PRIuPTR         PRIu32
    #define PRIxPTR         PRIx32
    #define PRIXPTR         PRIX32
#else
    #error "Unsupported platform!"
#endif


// The fscanf macros for signed integers are:
#define SCNd8           "d"
#define SCNi8           "i"
#define SCNdLEAST8      SCNd8
#define SCNiLEAST8      SCNi8
#define SCNdFAST8       SCNd8
#define SCNiFAST8       SCNi8

#define SCNd16          "hd"
#define SCNi16          "hi"
#define SCNdLEAST16     SCNd16
#define SCNiLEAST16     SCNi16
#define SCNdFAST16      SCNd16
#define SCNiFAST16      SCNi16

#define SCNd32          "ld"
#define SCNi32          "li"
#define SCNdLEAST32     SCNd32
#define SCNiLEAST32     SCNi32
#define SCNdFAST32      SCNd32
#define SCNiFAST32      SCNi32

#define SCNd64          "I64d"
#define SCNi64          "I64i"
#define SCNdLEAST64     SCNd64
#define SCNiLEAST64     SCNi64
#define SCNdFAST64      SCNd64
#define SCNiFAST64      SCNi64

#define SCNdMAX         SCNd64
#define SCNiMAX         SCNi64

#if defined _M_X64 || defined _M_AMD64
    #define SCNdPTR         SCNd64
    #define SCNiPTR         SCNi64
#elif defined _M_IX86
    #define SCNdPTR         SCNd32
    #define SCNiPTR         SCNi32
#else
    #error "Unsupported platform!"
#endif  // _WIN64 ]

// The fscanf macros for unsigned integers are:
#define SCNo8           "o"
#define SCNu8           "u"
#define SCNx8           "x"
#define SCNX8           "X"
#define SCNoLEAST8      SCNo8
#define SCNuLEAST8      SCNu8
#define SCNxLEAST8      SCNx8
#define SCNXLEAST8      SCNX8
#define SCNoFAST8       SCNo8
#define SCNuFAST8       SCNu8
#define SCNxFAST8       SCNx8
#define SCNXFAST8       SCNX8

#define SCNo16          "ho"
#define SCNu16          "hu"
#define SCNx16          "hx"
#define SCNX16          "hX"
#define SCNoLEAST16     SCNo16
#define SCNuLEAST16     SCNu16
#define SCNxLEAST16     SCNx16
#define SCNXLEAST16     SCNX16
#define SCNoFAST16      SCNo16
#define SCNuFAST16      SCNu16
#define SCNxFAST16      SCNx16
#define SCNXFAST16      SCNX16

#define SCNo32          "lo"
#define SCNu32          "lu"
#define SCNx32          "lx"
#define SCNX32          "lX"
#define SCNoLEAST32     SCNo32
#define SCNuLEAST32     SCNu32
#define SCNxLEAST32     SCNx32
#define SCNXLEAST32     SCNX32
#define SCNoFAST32      SCNo32
#define SCNuFAST32      SCNu32
#define SCNxFAST32      SCNx32
#define SCNXFAST32      SCNX32

#define SCNo64          "I64o"
#define SCNu64          "I64u"
#define SCNx64          "I64x"
#define SCNX64          "I64X"
#define SCNoLEAST64     SCNo64
#define SCNuLEAST64     SCNu64
#define SCNxLEAST64     SCNx64
#define SCNXLEAST64     SCNX64
#define SCNoFAST64      SCNo64
#define SCNuFAST64      SCNu64
#define SCNxFAST64      SCNx64
#define SCNXFAST64      SCNX64

#define SCNoMAX         SCNo64
#define SCNuMAX         SCNu64
#define SCNxMAX         SCNx64
#define SCNXMAX         SCNX64

#if defined _M_X64 || defined _M_AMD64
    #define SCNoPTR       SCNo64
    #define SCNuPTR       SCNu64
    #define SCNxPTR       SCNx64
    #define SCNXPTR       SCNX64
#elif defined _M_IX86
    #define SCNoPTR       SCNo32
    #define SCNuPTR       SCNu32
    #define SCNxPTR       SCNx32
    #define SCNXPTR       SCNX32
#else
    #error "Unsupported platform!"
#endif  // _WIN64 ]


#if defined __cplusplus
extern "C" {
    //  these functions are included in crt since vc++ 7.1 (7.0- unchecked)
    _Check_return_ _CRTIMP std::intmax_t __cdecl _strtoi64(const char *, char **, int);
    _Check_return_ _CRTIMP std::uintmax_t __cdecl _strtoui64(const char *, char **, int);

    _Check_return_ _CRTIMP std::intmax_t __cdecl _wcstoi64(const wchar_t *, wchar_t **, int);
    _Check_return_ _CRTIMP std::uintmax_t __cdecl _wcstoui64(const wchar_t *, wchar_t **, int);
}
#else
    _Check_return_ _CRTIMP intmax_t __cdecl _strtoi64(const char *, char **, int);
    _Check_return_ _CRTIMP uintmax_t __cdecl _strtoui64(const char *, char **, int);
    
    _Check_return_ _CRTIMP intmax_t __cdecl _wcstoi64(const wchar_t *, wchar_t **, int);
    _Check_return_ _CRTIMP uintmax_t __cdecl _wcstoui64(const wchar_t *, wchar_t **, int);
    
#endif



#if defined __cplusplus
namespace std {
#endif
    // 7.8 Format conversion of integer types
    struct imaxdiv_t {
        intmax_t quot;
        intmax_t rem;
    };

    // 7.8.2 Functions for greatest-width integer types
    // 7.8.2.1 The imaxabs function
    #if !defined __INLINE_IMAXABS
        static
    #else
        inline
    #endif
        intmax_t imaxabs(intmax_t j) 
        {
            return (j >= 0 ? j : -j);
        }

    // 7.8.2.2 The imaxdiv function
    #if !defined __INLINE_IMAXDIV
        static
    #else
        inline
#endif
        struct imaxdiv_t imaxdiv(intmax_t numer, intmax_t denom)
        {
            struct imaxdiv_t result;
            result.quot = numer / denom;
            result.rem = numer % denom;
            return result;
        }

    #if !defined __INLINE_INTTYPES_STR
        static
    #else
        inline
    #endif
        intmax_t strtoimax(const char *nptr, char **endptr, int base)
        {   return _strtoi64(nptr, endptr, base);   }

    #if !defined __INLINE_INTTYPES_STR
        static
    #else
        inline
    #endif
            uintmax_t strtoumax(const char *nptr, char **endptr, int base)
        {   return _strtoui64(nptr, endptr, base);   }

    #if !defined __INLINE_INTTYPES_STR
        static
    #else
        inline
    #endif
            intmax_t wcstoimax(const wchar_t *nptr, wchar_t **endptr, int base)
        {   return _wcstoi64(nptr, endptr, base);   }
        
    #if !defined __INLINE_INTTYPES_STR
        static
    #else
        inline
    #endif
            uintmax_t wcstoumax(const wchar_t *nptr, wchar_t **endptr, int base)
        {   return _wcstoui64(nptr, endptr, base);   }

#if defined __cplusplus
}
#endif

#endif // INTTYPES_MSVC_H